import scrapy
from scrapy.exceptions import CloseSpider  # 导入CloseSpider异常，用于关闭爬虫
from urllib.parse import urljoin  # 导入urljoin用于处理URL拼接

class WeatherSpider(scrapy.Spider):
    name = 'weather_spider'  # 爬虫名称
    allowed_domains = ['weather.com.cn']  # 允许的域名
    start_urls = ['http://www.weather.com.cn']  # 起始URL，爬虫从这里开始

    custom_settings = {
        'ITEM_PIPELINES': {
            'weather_images.pipelines.ImagePipeline': 1,  # 启用图片下载管道
        },
        'IMAGES_STORE': 'images',  # 图片存储路径
        'LOG_LEVEL': 'INFO',  # 日志级别
        'CONCURRENT_REQUESTS': 1,  # 设置为单线程
    }

    total_images = 0  # 统计下载的图片数量
    max_images = 108  # 设置最大下载数量
    max_pages = 8     # 设置最大爬取页面数量
    pages_crawled = 0 # 已爬取页面数量

    def parse(self, response):
        # 从响应中提取所有图片的src属性
        image_urls = response.css('img::attr(src)').getall()
        # 将相对URL转换为绝对URL
        image_urls = [urljoin(response.url, url) for url in image_urls]
        # 过滤出有效的HTTP URL
        image_urls = [url for url in image_urls if url.startswith('http')]

        if not image_urls:  # 如果没有找到有效的图片URL
            self.log('No valid image URLs found on this page.')
            return  # 直接返回，不进行后续操作

        # 遍历有效的图片URL
        for url in image_urls:
            if self.total_images < self.max_images:  # 如果还未达到最大图片数量
                yield {'image_urls': [url]}  # 产出包含图片URL的字典
                self.log(f'Download URL: {url}')  # 记录下载的URL
                self.total_images += 1  # 增加已下载的图片数量

        # 检查是否达到最大图片数量
        if self.total_images >= self.max_images:
            self.log(f'Reached max image limit: {self.max_images}. Closing spider.')
            raise CloseSpider(reason='Reached max image limit')  # 关闭爬虫

        # 处理分页，这里假设有一个简单的分页机制
        self.pages_crawled += 1  # 增加已爬取页面数量
        if self.pages_crawled < self.max_pages:  # 如果还未达到最大页面数量
            next_page = response.css('a::attr(href)').get()  # 获取下一个页面的链接
            if next_page:  # 如果找到下一个页面的链接
                yield response.follow(next_page, self.parse)  # 继续爬取下一个页面
